﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TaiwuZD
{

    public class TwDictionary : Dictionary<string, string>
    {
        public string DefaultValue { get; set; } = "0";

        public new string this[string key]
        {
            get
            {
                if (Keys.Contains(key))
                    return base[key];
                else
                    return DefaultValue;
            }
            set
            {
                if (Keys.Contains(key))
                    base[key] = value;
                else if (value != DefaultValue)
                    Add(key, value);
            }
        }

        public string this[int key]
        {
            get
            {
                return this[key.ToString()];
            }
            set
            {
                this[key.ToString()] = value;
            }
        }

        public TwDictionary() { }

        public TwDictionary(Dictionary<string, string> dic)
        {
            foreach (var item in dic)
            {
                if (item.Value.Trim() != "0")
                Add(item.Key, item.Value);
            }
        }
        public TwDictionary(Dictionary<int, string> dic)
        {
            foreach (var item in dic)
            {
                if (item.Value.Trim() != "0")
                    Add(item.Key.ToString(), item.Value);
            }
        }
    }

    public abstract class TwObject:BindableBase,ICloneable
    {
        
        public virtual int Id
        {
            get { return int.Parse(DataShop[999]); }
            protected set { DataShop[999] = value.ToString(); }
        }

        public virtual string Name
        {
            get { return DataShop[0]; }
            protected set { DataShop[0] = value; }
        }

        public virtual string Description
        {
            get { return DataShop[99]; }
            protected set { DataShop[99] = value; }
        }

        protected virtual string[] RequiredFileds { get { return new string[]{ "0"}; } }

        [JsonProperty]
        protected TwDictionary DataShop { get; set; } = new TwDictionary();


        public virtual string this[string key]
        {
            get
            {
                if (DataShop.ContainsKey(key))
                    return DataShop[key];
                else
                    return GetDefaultValue(key);// DataShop.DefaultValue;
            }
        }

        public virtual string this[int key]
        {
            get
            {
                return this[key.ToString()];
            }
        }

        public T ValueAt<T>(string key) where T : struct
        {
            var tmp = this[key];

            if (typeof(T) == typeof(int))
            {
                int d = 0;
                int.TryParse(tmp, out d);
                return (T)Convert.ChangeType(d, typeof(T));
            }
            else if (typeof(T).IsEnum)
            {
                int d = 0;
                int.TryParse(tmp, out d);
                return (T)Enum.ToObject(typeof(T), d);
            }
            else
                return default(T);
        }
        public T ValueAt<T>(int key) where T : struct
        {
            var str = key.ToString();
            if (str == "ND") str = "0";
            return ValueAt<T>(str);
        }

        protected void SetData(JProperty jp)
        {
            foreach (JProperty item in jp.Value)
            {
                DataShop[item.Name] = item.Value.ToString();
            }
        }

        protected void SetData(int key,string value)
        {
            var kk = key.ToString();
            if (DataShop.ContainsKey(kk))
                DataShop[kk] = value;
            else
                DataShop.Add(kk, value);
        }

        protected void SetData(int key, int value)
        {
            var kk = key.ToString();
            if (DataShop.ContainsKey(kk))
                DataShop[kk] = value.ToString();
            else
                DataShop.Add(kk, value.ToString());
        }

        protected void SetData(string key, string value)
        {  
            if (DataShop.ContainsKey(key))
                DataShop[key] = value;
            else
                DataShop.Add(key, value);
        }

        protected void SetData(Dictionary<int, string> savedata)
        {
            foreach (var item in savedata)
            {
                DataShop[item.Key] = item.Value;
            }
        }

        public static T LoadFromJson<T>(JProperty jp) where T : class
        {
            if (typeof(T) == typeof(TwItemPower))
                return LoadItemPower(jp) as T;
            else if (typeof(T) == typeof(TwItemTemplate))
                return LoadItems(jp) as T;
            else if (typeof(T) == typeof(TwBuilding))
                return LoadTwBuildings(jp) as T;
            else if (typeof(T) == typeof(TwGongFa))
                return LoadTwGongFa(jp) as T;

            return default(T);
        }

        private static object LoadTwGongFa(JProperty jp)
        {
            TwGongFa gf = new TwGongFa();
            gf.SetData(jp);

            gf.Id = Convert.ToInt32(jp.Name); 
            gf.Name = gf["0"];
            gf.Description = gf["99"]; 

            return gf;
        }

        private static object LoadTwBuildings(JProperty jp)
        {
            TwBuilding ti = new TwBuilding();

            ti.SetData(jp);

            ti.Id = Convert.ToInt32(jp.Name);// ti.ValueAt<int>(999);
            ti.Name = ti["0"];
            ti.Description = ti["99"];
            if (ti.Id > 110)
                ti.Category = 1;


            return ti;
        }

        private static TwItemPower LoadItemPower(JProperty jp)
        {
            TwItemPower val = new TwItemPower();
            val.Id = int.Parse(jp.Name);

            val.SetData(jp);
            val.Name = val[0];
            val.Description = val[99];

            return val;
        }

        private static TwItemTemplate LoadItems(JProperty jp)
        {
            TwItemTemplate ti = new TwItemTemplate();

            ti.SetData(jp);

            ti.Id = ti.ValueAt<int>(999);
            ti.Name = ti["0"];
            ti.Description = ti["99"];

            return ti;
        }

        public T Copy<T>() where T : TwObject
        {
            T x = typeof(T).GetConstructor(Type.EmptyTypes).Invoke(null) as T;
            x.Id = Id;
            x.Name = Name;
            x.Description = Description;
            x.DataShop = new TwDictionary(this.DataShop);
            return x;
        }

        public abstract object Clone();


        protected virtual string GetDefaultValue(string key)
        {
            return "0";
        }


        public string DebugInfo
        {
            get
            {
                return string.Join("\n", DataShop.OrderBy(x => int.Parse(x.Key)).Select(x => $"{ GameAssets.TwID[x.Key]}({x.Key}):{x.Value}"));
            }
        }


        
    }

    

}
